package lock;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 是一种悲观思想，即认为写多读少，遇到并发写的可能性高，每次去拿数据的时候都认为其他线程会修改，所以每次读写数据都会认为其他线程会修改，
 * 所以每次读写数据时都会上锁。其他线程想要读写这个数据时，会被这个线程block，直到这个线程释放锁然后其他线程获取到锁。
 *
 * Java中的悲观锁： synchronized修饰的方法和方法块、ReentrantLock。
 */

public class PessimisticLockExample {

    //这个共享资源用于synchronized 验证锁的实现
    private int synSharedResource = 0;

    //这个共享资源用于ReentrantLock 验证锁的实现
    private int sharedResource = 0;
    private final Lock lock = new ReentrantLock();

    //synchronized修斯的 的 增量方法
    public synchronized void synIncrement() {
        synSharedResource++;
        System.out.println(Thread.currentThread().getName() + " incremented sharedResource to " + synSharedResource);
    }

    //synchronized修斯的 的 增量方法
    public synchronized int getSynSharedResource() {
       return synSharedResource;
    }

    //ReentrantLock 的 增量方法
    public void increment() {
        lock.lock(); // 获取锁
        try {
            // 临界区：对共享资源进行操作
            sharedResource++;
            System.out.println(Thread.currentThread().getName() + " incremented sharedResource to " + sharedResource);
        } finally {
            lock.unlock(); // 释放锁
        }
    }
    //获取共享资源
    public int getSharedResource() {
        lock.lock(); // 获取锁
        try {
            return sharedResource;
        } finally {
            lock.unlock(); // 释放锁
        }
    }

    public static void main(String[] args) {
        PessimisticLockExample example = new PessimisticLockExample();

        // 创建多个线程来测试悲观锁
        Runnable task = () -> {
            for (int i = 0; i < 5; i++) {
                try {
                    example.increment();
                    Thread.sleep(1000); // 模拟其他操作
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
        };

        // 创建多个线程来测试悲观锁
        Runnable task2 = () -> {
            for (int i = 0; i < 5; i++) {
                try {
                    example.synIncrement();
                    Thread.sleep(1000); // 模拟其他操作
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
        };

        Thread thread1 = new Thread(task2, "Thread-1");
        Thread thread2 = new Thread(task2, "Thread-2");

        thread1.start();
        thread2.start();

        try {
            thread1.join();
            thread2.join();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }

        System.out.println("Final sharedResource value: " + example.getSynSharedResource());
    }
}
